package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"network_study2/src/server"
	"os"
	"path/filepath"
)

// http 客户端

func main() {

	fmt.Println("http ： client start...")

	/*	reader := bufio.NewReader(os.Stdin)

		// 读取字符串
		fmt.Print("请输入你的名字：")
		name, _ := reader.ReadString('\n')
		fmt.Println("去除开头和结尾的空白字符（包括空格、制表符、换行符等）", strings.TrimSpace(name))
		fmt.Println("获取输入的名字：", name)

		// 读取整数
		fmt.Print("请输入你的年龄：")
		ageStr, _ := reader.ReadString('\n')
		ageStr = strings.TrimSpace(ageStr)
		age, _ := strconv.Atoi(ageStr)
		fmt.Println("获取输入的年龄：", age)
		fmt.Println()

		// 读取浮点数
		fmt.Print("请输入你的身高：")
		heightStr, _ := reader.ReadString('\n')
		heightStr = strings.TrimSpace(heightStr)
		height, _ := strconv.ParseFloat(heightStr, 64)
		fmt.Println("获取输入的身高：", height)*/

	//login()

	//findUserByPhone()

	//findList()

	/*if err := uploadFile(); err != nil {
		fmt.Printf("上传失败: %v\n", err)
	}*/

	/*str, err := listFile()
	if err != nil {
		fmt.Printf("查询文件列表失败: %v\n", err)
	}
	fmt.Println("查询文件列表：", str)*/

	if err := downloadFile(); err != nil {
		fmt.Printf("文件下载失败: %v\n", err)
	}
}

/*
 * POST用户登录
 * 请求json，响应json
 */
func login() {
	fmt.Println("用户登录发送请求...")
	// map模拟参数
	//var loginParam = map[string]interface{}{
	//	"Phone": "123",
	//	"Pwd":   "123456",
	//}

	// 匿名结构体：模拟参数
	loginParam := struct {
		Phone string
		Pwd   string
	}{
		Phone: "123",    // 账号
		Pwd:   "123456", // 密码
	}
	fmt.Println("\t模拟参数：", loginParam)
	strjson1, err1 := json.Marshal(loginParam)
	if err1 != nil {
		panic(err1)
	}

	var param1 = string(strjson1)
	fmt.Println("\t请求参数(json)：", param1)
	resp1, _ := http.Post("http://127.0.0.1:60000/login", "application/json", bytes.NewBuffer(strjson1))
	fmt.Println("\t响应结果：", resp1)

	body, err := io.ReadAll(resp1.Body)
	if err != nil {
		panic(err)
	}

	responseBody := map[string]interface{}{}
	if err := json.Unmarshal(body, &responseBody); err != nil {
		fmt.Println("\t解析响应失败:", err)
	}
	fmt.Println("\t获取响应：", responseBody)

	jsonstr, _ := json.Marshal(responseBody)
	fmt.Println("\t获取响应(json)：", string(jsonstr))
	fmt.Println("用户登录发送请求结束...")
}

/*
 * GET根据手机号查找信息
 * 请求字符串，响应字符串
 */
func findUserByPhone() {
	fmt.Println("根据手机号查找信息发送请求...")
	baseUrl := "http://127.0.0.1:60000/findUserByPhone"
	// 解析基础url
	u, err := url.Parse(baseUrl)
	if err != nil {
		panic(err)
	}

	// 设置参数 使用url.Parse 构建
	pathParam := url.Values{}
	//pathParam.Add("phone", "123")
	u.RawQuery = pathParam.Encode()
	fmt.Printf("\t完整URL: %s \n", u.String())

	resp, _ := http.Get(u.String())
	defer resp.Body.Close() //关闭

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	fmt.Println("\t响应内容：", resp)
	fmt.Println("\t响应状态：", resp.Status)
	fmt.Println("\t响应头：", resp.Header)
	fmt.Println("\t响应结果体：", string(body))

	fmt.Println("根据手机号查找信息请求结束...")
}

/*
 * GET 查询列表
 * 请求JSON，响应JSON
 */
func findList() {
	fmt.Println("查询列表发送请求...")
	baseUrl := "http://127.0.0.1:60000/findList"

	u, err := url.Parse(baseUrl)
	if err != nil {
		panic(err)
	}
	param := url.Values{}
	param.Add("name", "小")
	u.RawQuery = param.Encode()
	fmt.Println("\t请求参数:", u.String())

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("连接服务端失败: %v", err)
		return
		//panic(err) panic 应该用于真正异常的情况，而不是常规错误处理
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	fmt.Println("\t响应内容：", resp)
	fmt.Println("\t响应状态：", resp.Status)
	fmt.Println("\t响应头：", resp.Header)
	fmt.Println("\t响应结果体：", string(body))

	//// map 接收响应体
	//resMap := map[string]interface{}{}
	//if err := json.Unmarshal(body, &resMap); err != nil {
	//	panic(err)
	//}
	//fmt.Println(resMap)
	//fmt.Println(resMap["data"])
	//for _, v := range resMap["data"].([]interface{}) {
	//	fmt.Println(v.(map[string]interface{}))
	//	//fmt.Println(v.(map[string]interface{})["name"])
	//	//fmt.Println(v.(map[string]interface{})["email"])
	//	//fmt.Println(v.(map[string]interface{})["phone"])
	//}

	// 结构体接收响应
	resbody := server.Result{}
	if err := json.Unmarshal(body, &resbody); err != nil {
		panic(err)
	}
	// 获取返回体data内容
	dataArr := resbody.Data.([]interface{})
	for _, v := range dataArr {
		fmt.Printf("\t  %v, %T \n ", v, v)
		// 将map 转json字节
		jsonByte, _ := json.Marshal(v.(map[string]interface{}))
		// 将json字节转 结构体
		var user1 user
		json.Unmarshal(jsonByte, &user1)
		fmt.Printf("\tuser结构体  %v, %T \n ", v, v)
		fmt.Println("手机号：", user1.Phone)
	}

	fmt.Println("查询列表请求结束...")
}

type user struct {
	Id    int    `json:"id"`
	Name  string `json:"name"`
	Sex   bool   `json:"sex"`
	Phone string `json:"phone"`
	Pwd   string `json:"pwd"`
	Email string `json:"email"`
}

/*
 * POST 文件上传
 * 请求表单，响应JSON
 */
func uploadFile() error {

	filename := "E:\\case.txt"
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("打开文件失败，%v", err)
	}
	defer file.Close() //关闭文件

	// 创建表单
	form := &bytes.Buffer{}
	writer := multipart.NewWriter(form)

	// 向表单中添加文件
	part, err := writer.CreateFormFile("file", filepath.Base(filename))
	if err != nil {
		return fmt.Errorf("向表单中添加文件失败%v", err)
	}

	// 复制文件内容
	_, err = io.Copy(part, file)
	if err != nil {
		return fmt.Errorf("复制文件内容失败: %v", err)
	}

	// 关闭writer
	err = writer.Close()
	if err != nil {
		return fmt.Errorf("关闭writer失败%v", err)
	}

	// 创建POST请求
	req, err := http.NewRequest("POST", "http://127.0.0.1:60000/uploadFile", form)
	if err != nil {
		return fmt.Errorf("创建Post请求失败, %v", err)
	}

	// 设置请求头类型
	req.Header.Set("Content-Type", writer.FormDataContentType())

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送请求失败, %v", err)
	}
	defer resp.Body.Close()

	// 读取响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %v", err)
	}

	//if resp.StatusCode != http.StatusOK {
	//	return fmt.Errorf("服务器返回错误: %s - %s", resp.Status, string(respBody))
	//}

	fmt.Printf("上传成功: %s\n", string(respBody))
	return nil
}

/*
 * GET 查询所有上传文件
 */
func listFile() (string, error) {

	resp, err := http.Get("http://127.0.0.1:60000/listFile")
	if err != nil {
		return "", fmt.Errorf("请求失败： %v", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取返回体失败 %v", err)
	}

	fmt.Println("响应内容：", string(body))

	return string(body), nil
}

/*
 * GET 下载文件
 */
func downloadFile() error {
	var filename string = "case.txt"
	var url string = "http://127.0.0.1:60000/downloadFile?fileName=" + filename
	var savePath string = "./downloaded_example.txt"
	// 创建请求
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return fmt.Errorf("创建请求失败: %v", err)
	}

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		respBody, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("服务器返回错误: %s - %s", resp.Status, string(respBody))
	}

	// 创建目标文件
	out, err := os.Create(savePath)
	if err != nil {
		return fmt.Errorf("创建文件失败: %v", err)
	}
	defer out.Close()

	// 复制响应内容到文件
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return fmt.Errorf("保存文件失败: %v", err)
	}

	fmt.Printf("文件下载成功: %s -> %s\n", filename, savePath)
	return nil
}
